﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace Sofire.Data.XSql
{
    internal class XSqlParameterNode : XSqlNameNodeBase, IXSqlParameterNode
    {
        public const string NodeName = "parameter";

        private string _To;
        public string To
        {
            get
            {
                return this._To;
            }
            set
            {
                this._To = value;
            }
        }

        private System.Data.ParameterDirection _Direction = System.Data.ParameterDirection.Input;
        public System.Data.ParameterDirection Direction
        {
            get
            {
                return this._Direction;
            }
            set
            {
                this._Direction = value;
            }
        }

        private bool _Required;
        public bool Required
        {
            get { return _Required; }
            set { _Required = value; }
        }

        public override XSqlType Type
        {
            get { return XSqlType.Parameter; }
        }

        public override XObject CreateXObject()
        {
            XElement element = new XElement(NodeName);
            element.SetAttributeValue(XSqlAttributes.Name, this.Name);
            element.SetAttributeValue(XSqlAttributes.To, this._To);

            if(this._Required) element.SetAttributeValue(XSqlAttributes.Required, "true");
            if(this._Direction != System.Data.ParameterDirection.Input) element.SetAttributeValue(XSqlAttributes.Direction, (int)this._Direction);

            return element;
        }

        protected override void Load(XmlNode node)
        {
            base.Load(node);

            this._To = this.TryGetAttribute(node, XSqlAttributes.To);
            var direction = this.TryGetAttribute(node, XSqlAttributes.Direction);
            if(direction != null)
            {
                direction = direction.Trim();
                switch(direction)
                {
                    case "2":
                    case "3":
                    case "6":
                        this._Direction = (System.Data.ParameterDirection)int.Parse(direction);
                        break;
                    case "Output":
                    case "output":
                        this._Direction = System.Data.ParameterDirection.Output;
                        break;
                    case "inputoutput":
                    case "inputOutput":
                    case "InputOutput":
                        this._Direction = System.Data.ParameterDirection.InputOutput;
                        break;
                    case "returnvalue":
                    case "returnValue":
                    case "ReturnValue":
                        this._Direction = System.Data.ParameterDirection.ReturnValue;
                        break;
                }
            }

            var required = this.TryGetAttribute(node, XSqlAttributes.Required);

            if(required == "true" || required == "True" || required == "1") this._Required = true;

        }

        public void InnerCompile(XSqlParameterCollection parameters)
        {
            XSqlBindItem item = new XSqlBindItem(this.Name);
            var name = item.Name;
            var p = parameters[name];

            if(p == null)
            {
                if(this._Direction != System.Data.ParameterDirection.Input)
                {
                    p = new ExecuteParameter(name, null);
                    parameters.Add(p);
                }
                else if(this._Required)
                {
                    this.ThrowException(XSqlError.NoExists, name);
                    return;
                }
            }
            p.Direction = this._Direction;

            item.ConvertParameter(p);

            if(!string.IsNullOrEmpty(this._To))
            {
                parameters.Remove(p);
                p.Name = this._To;
                parameters.Add(p);
            }
        }

        public override string Compile(XSqlParameterCollection parameters)
        {
            return null;
        }
    }
}
